/*
 * Author: James White
 * Last modified- 1/23/10 James
 * 
 */


package fatboy.communication;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.io.Serializable;


import junit.framework.Assert;

// Stores the commands to be executed across the network
public class Command implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	//private Method methodToRun;
	private Object[] paramVals;
	private ObjectID objID;
	private String methodName;
	private Class[] paramTypes;
	private Class callee;
	//private Object returnVal;

	public Command(ObjectID newID, String methName, Class[] types, Object[] params, Class callee) {
		objID = newID;
		paramVals = params;
		paramTypes = types;
		methodName = methName;
		this.callee= callee;
	}
	
	/**
	 * Gets object from Map and executes it
	 * 
	 * @return the return value of Object executed
	 */
	public Object excecute(){

		try{
			//ObjectLoader loader = new ObjectLoader();
			//Object objToRun = loader.getObject(objID);
			Object objToRun = ResidentDatabase.getObject(objID);
			//System.out.println(PortNumber.getRuntimePort());
			Method method = callee.getMethod(methodName, paramTypes);
			//System.out.println(objID.getObjID());
			if(objID.getObjID() != 0){
				Assert.assertNotNull(objToRun);
			}
			Object returnVal = method.invoke(objToRun, paramVals);
			//loader.setObject(objID, objToRun);
			//ResidentDatabase.setObject(objID, objToRun);
			return returnVal;
		}
		catch(NoSuchMethodException e){
			//System.out.println("Error occured with execute: "+e);
			return null;
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
			return null;
		} catch (IllegalAccessException e) {

			e.printStackTrace();
			return null;
		} catch (InvocationTargetException e) {

			e.printStackTrace();
			e.getCause().printStackTrace();
			return null;
		}	
	}

	/**
	 * 
	 * Checks to see if stored object has a return value
	 * 
	 * @return if object has return value or not
	 */
	public boolean hasReturn(){
		//ObjectLoader loader = new ObjectLoader();
		//Object objToRun = loader.getObject(objID);
		Object objToRun = ResidentDatabase.getObject(objID);
		try {
			Method method = callee.getMethod(methodName, paramTypes);
			//System.out.println("Return Value: "+method.getReturnType());
			if(!method.getReturnType().equals(void.class)){
				return true;
			}
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}
	public String toString(){
		String ret = callee.getSimpleName() +"."+ methodName + "(";
		for(Class c : paramTypes){
			ret += c.getSimpleName() +" ";
		}
		return ret + ")";
	}

}
